home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 363_02 / opparse.c < prev    next >
C/C++ Source or Header  |  1991-12-15  |  48KB  |  1,132 lines

  1. /***********************************************************************
  2.  *
  3.  *      OPPARSE.C
  4.  *      Operand Parser for 68000 Assembler
  5.  *
  6.  *    Function: isXreg()
  7.  *      Parses Index Register specification, inserts the upper byte flags
  8.  *      (see below) into extension word.
  9.  *
  10.  *    Function: opParse()
  11.  *      Parses an operand of the 68020 assembly language instruction and
  12.  *      attempts to recognize its addressing mode. The p argument points to
  13.  *      the string to be evaluated, and the function returns a pointer to the
  14.  *      first character beyond the end of the operand.
  15.  *      The function returns a description of the operands that it parses in
  16.  *      an opDescriptor structure. The fields of the operand descriptor are
  17.  *      filled in as appropriate for the mode of the operand that was found:
  18.  *
  19.  *      mode    returns the address mode (symbolic values defined in ASM.H)
  20.  *      data    returns the displacement or address or immediate value
  21.  *      reg     returns the address or data register number
  22.  *      size    returns the size of absolute address (WORD or LONG)
  23.  *      xtenWord returns the indexed operation first extension word. The
  24.  *              7 MSBits are filled in by isXreg(), the 9 LSBits - by opparse.
  25.  *      bfXtenWord bit field extension word
  26.  *      outDisp returns the outer displacement of an indexed operation
  27.  *      backRef TRUE if data is the value of an expression that contains only
  28.  *              constants and backwards references; FALSE otherwise.
  29.  *      odBackRef TRUE if outer displacement is the value of an expression
  30.  *              that contains only constants and backward references; FALSE
  31.  *              otherwise.
  32.  *
  33.  *      The argument errorPtr is used to return an error code via the standard
  34.  *      mechanism.
  35.  *
  36.  *   Usage: char *opParse(char *p, opDescriptor *d, int *errorPtr)
  37.  *
  38.  *      Author: Paul McKee
  39.  *      ECE492    North Carolina State University, 10/10/86
  40.  *
  41.  *    Revision: 10/26/87
  42.  *      Altered the immediate mode case to correctly flag
  43.  *      constructs such as "#$1000(A5)" as syntax errors.
  44.  *
  45.  *      Modified A.E. Romer. Version 1.0
  46.  *          17 March 1991 - converted to ANSI
  47.  *          21 March 1991 - .w and .l suffixes allowed in absolute addressing
  48.  *          May      1991 - isXreg() added.
  49.  *          Summer   1991 - conversion to 68020 format of indirection 
  50.  *                          instruction, index SCALE implementation, addition 
  51.  *                          of 68020 specific instructions
  52.  *
  53.  ************************************************************************/
  54.  
  55.  
  56. #include <stdio.h>
  57. #include <ctype.h>
  58. #include "asm.h"
  59.  
  60.  
  61. extern char pass2;
  62. extern long loc;
  63.  
  64.  
  65. #define isTerm(c)   (isspace(c)         /* operand field terminator */\
  66.                         || (c == ',')   /* source/destination separator */\
  67.                         || c == '{'     /* bit field specification start */\
  68.                         || c == '\0')   /* line terminator */
  69.  
  70. #define isRegNum(c) ((c >= '0') && (c <= '7'))
  71.  
  72.  
  73. char *isXreg(char *p, opDescriptor *d, int *errorPtr)
  74.     {
  75.     long scale;
  76.  
  77.     if ((p[0] == 'A' || p[0] == 'D') && isRegNum(p[1]))
  78.                         /* set index register field in the extension word */
  79.         {
  80.         d->xtenWord |= XREG_NUM(p[1] - '0');
  81.         if (p[0] == 'A')
  82.             d->xtenWord |= XREG_IS_An;
  83.  
  84. /* neither size nor scale specified */
  85.         if (p[2] == ')' || p[2] == ']' || p[2] ==',')
  86.             return p+2;             /* Default index register size
  87.                                      * and scale, null displacement */
  88.  
  89. /* size specified */
  90.         else if (p[2] == '.')
  91.             {
  92.             /* Determine size of index register */
  93.             if (p[3] == 'W')
  94.                 ;                   /* default */
  95.             else if (p[3] == 'L')
  96.                 d->xtenWord |= XSIZE_LONG;
  97.             else
  98.                 {
  99.                 NEWERROR(*errorPtr, SYNTAX);
  100.                 return NULL;
  101.                 }
  102.             if (p[4] == ')' || p[4] == ']' || p[4] == ',')
  103.                                                     /* no scale specified */
  104.                 return p+4;                         /* default scale is 1 */
  105.  
  106.             else if (p[4] == '*')                   /* scale specified */
  107.                 {
  108.                 p = eval(p+5, &scale, &d->backRef, errorPtr);
  109.                 if (*errorPtr > SEVERE)
  110.                     return NULL;
  111.                 else if (p[0] != ')' && p[0] != ']' && p[0] != ',')
  112.                                                     /* missing terminator */
  113.                     {
  114.                     NEWERROR(*errorPtr, SYNTAX);
  115.                     return NULL;
  116.                     }
  117.                 else
  118.                     switch (scale)
  119.                         {
  120.                         case 1: return p;
  121.                         case 2: d->xtenWord |= SCALE_TWO; return p;
  122.                         case 4: d->xtenWord |= SCALE_FOUR; return p;
  123.                         case 8: d->xtenWord |= SCALE_EIGHT; return p;
  124.                         default: NEWERROR(*errorPtr, SYNTAX); return NULL;
  125.                         }
  126.                 }
  127.             }
  128.  
  129.  /* size not specified, scale specified */
  130.         else if (p[2] == '*')
  131.             {
  132.             p = eval(p+3, &scale, &d->backRef, errorPtr);
  133.             if (*errorPtr > SEVERE)
  134.                 return NULL;
  135.             else if (p[0] != ')' && p[0] != ']')
  136.                 {
  137.                 NEWERROR(*errorPtr, SYNTAX);
  138.                 return NULL;
  139.                 }
  140.             else
  141.                 switch (scale)
  142.                     {
  143.                     case 1: return p;
  144.                     case 2: d->xtenWord |= SCALE_TWO; return p;
  145.                     case 4: d->xtenWord |= SCALE_FOUR; return p;
  146.                     case 8: d->xtenWord |= SCALE_EIGHT; return p;
  147.                     default: NEWERROR(*errorPtr, SYNTAX); return NULL;
  148.                     }
  149.             }
  150.  
  151.         else                    /* neither ')', nor '.', nor '*' follows Xn */
  152.             {
  153.             NEWERROR(*errorPtr, SYNTAX);
  154.             return NULL;
  155.             }
  156.         }
  157.     else                                    /* incorrect indexing syntax */
  158.         return NULL;
  159.     }
  160.  
  161.  
  162. char *opParse(char *p, opDescriptor *d, int *errorPtr)
  163.     {
  164.     char *t;                                        /* temporary pointers */
  165.     long value;
  166.     char ref;
  167.     int  error;
  168.  
  169.     d->xtenWord = 0;        /* initialize */
  170.  
  171.     /**********************************************************\
  172.      *****      data or address register direct:          *****
  173.      *****              "Dn" or "An"                      *****
  174.     \**********************************************************/
  175.  
  176.     if (isRegNum(p[1]) && isTerm(p[2]))
  177.         {
  178.         if (p[0] == 'D')
  179.             {
  180.             d->mode = DnDirect;
  181.             d->reg = p[1] - '0';
  182.             return (p + 2);
  183.             }
  184.         else if (p[0] == 'A')
  185.             {
  186.             d->mode = AnDirect;
  187.             d->reg = p[1] - '0';
  188.             return (p + 2);
  189.             }
  190.         }
  191.  
  192.     /**********************************************************\
  193.      *****          Stack Pointer (A7) direct:            *****
  194.      *****                  "SP"                          *****
  195.     \**********************************************************/
  196.  
  197.     if (p[0] == 'S' && p[1] == 'P' && isTerm(p[2]))
  198.         {
  199.         d->mode = AnDirect;
  200.         d->reg = 7;
  201.         return (p + 2);
  202.         }
  203.  
  204.     /**********************************************************\
  205.      *****          Address register indirect:            *****
  206.      *****      "(An)", "(An)+", "(SP)", or "(SP)+"       *****
  207.     \**********************************************************/
  208.  
  209.     if (p[0] == '('
  210.             && ((p[1] == 'A' && isRegNum(p[2]))
  211.                                 || (p[1] == 'S' && p[2] == 'P'))
  212.             && p[3] == ')')
  213.         {
  214.  
  215.         if (p[1] == 'S')
  216.             d->reg = 7;
  217.         e